package com.budwk.app.sqfw.services.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.budwk.app.common.config.AppException;
import com.budwk.app.ocr_general.HttpUtil;
import com.budwk.app.sqfw.constants.CommonConstants;
import com.budwk.app.sqfw.services.VivoInterfaceService;
import com.budwk.starter.common.constant.RedisConstant;
import com.budwk.starter.common.result.Result;
import com.budwk.starter.common.result.ResultCode;
import com.google.common.collect.Maps;
import com.vivo.push.sdk.notofication.Message;
import com.vivo.push.sdk.server.Sender;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.impl.PropertiesProxy;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.*;


/**
 * @title: HuaweiPushServiceImpl
 * @Author Tan
 * @Date: 2023/7/25 17:10
 * @Version 1.0
 */
@IocBean
@Slf4j
public class VivoInterfaceServiceImpl implements VivoInterfaceService {

    @Inject
    private PropertiesProxy propertiesProxy;

    @Inject
    private RedisService redisService;

    @Override
    public void pushVivoMessage(String msgContent, String action, String token, String sqfwId) {
        try {
            //注册登录开发平台网站获取到的appSecret
            String appSecret = propertiesProxy.get("push.msg.vivo.appSecret", StringUtils.EMPTY);
            //注册登录开发平台网站获取到的appId和appKey
            int appId = propertiesProxy.getInt("push.msg.vivo.appId");
            String appKey = propertiesProxy.get("push.msg.vivo.appKey");
            int pushMode = propertiesProxy.getInt("push.msg.vivo.pushMode");
            Sender sender = new Sender(appSecret);
            com.vivo.push.sdk.notofication.Result result = sender.getToken(appId, appKey);
            sender.setAuthToken(result.getAuthToken());
            // 跳到对应的连接
            Map<String, String> clientCustomMap = new HashMap<>(2);
            clientCustomMap.put("action", action);
            clientCustomMap.put(action, sqfwId);
            Message singleMessage = new Message.Builder()
                    .regId(token)
                    .notifyType(4)
                    .title("祥云小助")
                    .content(msgContent)
                    .timeToLive(1000)
                    .skipType(1)
                    .classification(1) //消息类型 0：运营类消息，1：系统类消息
                    .clientCustomMap(clientCustomMap)
                    .networkType(-1)
                    .requestId(UUID.randomUUID().toString().replace("-", ""))
                    .pushMode(pushMode)
                    .build();
            log.info("push Vivo Message info :{}", JSONObject.toJSONString(singleMessage));
            com.vivo.push.sdk.notofication.Result resultMessage = sender.sendSingle(singleMessage);
            log.info("push Vivo Message result: {}", JSONObject.toJSONString(resultMessage));
            // 检查返回结果
            if (resultMessage == null) {
                throw new AppException();
            }
            if (resultMessage.getResult() != 0) {
                throw new AppException(JSONObject.toJSONString(resultMessage));
            }
        } catch (Exception e) {
            log.error("push Vivo Message error: ", e);
            throw new AppException();
        }
    }

    @Override
    public Result<?> getVivoApplyLatestVersion() {
        String redisDataKey = RedisConstant.WKCACHE + "vivo:getOnlineVersion:url:data";
        // 1 先从redis缓存中获取
        String versionData = redisService.get(redisDataKey);
        if (StringUtils.isNotEmpty(versionData)) {
            return Result.success(JSONObject.parseObject(versionData));
        }
        // 2 调用接口获取参数
        Optional<JSONObject> paramOptional = getParam();
        // 3 远程调用最新版本接口
        String url = propertiesProxy.get("vivo.getOnlineVersion.url");
        log.info("vivo getVersion query url: {}", url);
        JSONObject resJson = HttpUtil.doPostByJson(url, paramOptional.get(), null);
        log.info("vivo getVersion res: {}", resJson);
        int code = resJson.getInteger(CommonConstants.CODE);
        // 3 解析数据
        if (ResultCode.SUCCESS.getCode() == code) {
            // 取出data数据
            JSONObject dataJson = resJson.getJSONObject(CommonConstants.DATA);
            // 存入redis
            redisService.setex(redisDataKey, 1000, JSONObject.toJSONString(dataJson));
            return Result.success(dataJson);
        }
        String msg = resJson.getString(CommonConstants.MSG);
        return Result.error(msg);
    }

    /**
     * 获取加密验签
     */
    public Optional<JSONObject> getParam() {
        String secret = propertiesProxy.get("vivo.getOnlineVersion.secret");
        String account = propertiesProxy.get("vivo.getOnlineVersion.account");
        String packageName = propertiesProxy.get("vivo.getOnlineVersion.packageName");
        // 组装参数
        JSONObject params = new JSONObject();
        params.put("account", account);
        params.put("timestamp", System.currentTimeMillis());
        // 组装bizParam参数
        Map<String,String> bizParamsMap = Maps.newHashMap();
        bizParamsMap.put("packageName", packageName);
        params.put("bizParam", bizParamsMap);
        // 获取sign
        String sign = hmacSHA256(getUrlParamsFromMap(params), secret);
        params.put("sign", sign);
        return Optional.of(params);
    }

    /**
     * 根据传入的map，把map里的key value转换为接口的请求参数，并给参数按ascii码排序
     *
     * @param paramsMap 传入的map
     * @return 按ascii码排序的参数键值对拼接结果
     */
    private String getUrlParamsFromMap(Map<String, Object> paramsMap) {
        List<String> keysList = new ArrayList<>(paramsMap.keySet());
        Collections.sort(keysList);
        StringBuilder sb = new StringBuilder();
        for (String key : keysList) {
            if ("sign".equals(key)) {
                continue;
            }
            Object object = paramsMap.get(key);
            if (object == null) {
                continue;
            }
            sb.append(key).append(CommonConstants.EQUAL);
            if ("bizParam".equals(key)) {
                sb.append(JSON.toJSONString(object)).append(CommonConstants.ALSO);
            } else {
                sb.append(object).append(CommonConstants.ALSO);
            }
        }
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }
    /**
     * HMAC_SHA256 验签加密
     * */
    private String hmacSHA256(String data, String key) {
        try {
            byte[] secretByte = key.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec signingKey = new SecretKeySpec(secretByte, CommonConstants.HMACSHA256);
            Mac mac = Mac.getInstance(CommonConstants.HMACSHA256);
            mac.init(signingKey);
            byte[] dataByte = data.getBytes(StandardCharsets.UTF_8);
            byte[] by = mac.doFinal(dataByte);
            return byteArr2HexStr(by);
        } catch (Exception e) {
            log.error("HmacSHA256 error data: {}", data, e);
        }
        return null;
    }

    private String byteArr2HexStr(byte[] arrB) {
        int iLen = arrB.length;
        // 每个byte用两个字符才能表示，所以字符串的长度是数组长度的两倍
        StringBuilder sb = new StringBuilder(iLen * 2);
        for (int i = 0; i < iLen; i++) {
            int intTmp = arrB[i];
            // 把负数转换为正数
            while (intTmp < 0) {
                intTmp = intTmp + 256;
            }
            // 小于0F的数需要在前面补0
            if (intTmp < 16) {
                sb.append("0");
            }
            sb.append(Integer.toString(intTmp, 16));
        }
        return sb.toString();
    }
}
